﻿/* Autor: Achim Schnell */

using System;
using System.ComponentModel;
using System.Reflection;

namespace AppFx.ComponentModel.Descriptive
{
	/// <summary>
	/// Ein PropertyDescriptor zur Beschreibung von nested Properties.
	/// (Eigenschaften von Eigenschaften)
	/// </summary>
	public class CompiledNestedPropertyDescriptor : CompiledPropertyDescriptor
	{
		#region Properties

		/// <summary>
		/// PropertyDescriptor der übergeordneten Eigenschaft.
		/// </summary>
		protected PropertyDescriptor ParenDescriptor { get; set; }

		#endregion

		#region Constructors


		/// <summary>
		/// Erstelle eine neue Instanz der <see cref="CompiledNestedPropertyDescriptor"/>-Klasse.
		/// </summary>
		/// <param name="componentType">Typ der Komponente deren Eigenschaft beschrieben werden soll.</param>
		/// <param name="propertyInfo">Die Informationen zum zu beschreibenden Eigenschaftswert.</param>
		/// <param name="parentPropertyDescriptor">Der PropertyDescriptor zur übergeordneten Eigenschaft.</param>
		public CompiledNestedPropertyDescriptor(Type componentType, PropertyInfo propertyInfo, PropertyDescriptor parentPropertyDescriptor)
			: this(componentType, propertyInfo, parentPropertyDescriptor, parentPropertyDescriptor.Name + "." + propertyInfo.Name) { }

		/// <summary>
		/// Erstelle eine neue Instanz der <see cref="CompiledNestedPropertyDescriptor"/>-Klasse.
		/// </summary>
		/// <param name="componentType">Typ der Komponente deren Eigenschaft beschrieben werden soll.</param>
		/// <param name="propertyInfo">Die Informationen zum zu beschreibenden Eigenschaftswert.</param>
		/// <param name="parentPropertyDescriptor">Der PropertyDescriptor zur übergeordneten Eigenschaft.</param>
		/// <param name="name">Der Name, der als Name der Komponente gesetzt werden soll.</param>
		public CompiledNestedPropertyDescriptor(Type componentType, PropertyInfo propertyInfo, PropertyDescriptor parentPropertyDescriptor, string name)
			: base(componentType, propertyInfo, name)
		{
			if (parentPropertyDescriptor == null)
				throw new ArgumentNullException("parentPropertyDescriptor");
			ParenDescriptor = parentPropertyDescriptor;
		}

		#endregion

		#region Methods

		/// <summary>
		/// Ruft den Wert der beschriebenen Eigenschaft aus der Komponente ab.
		/// </summary>
		/// <param name="component">Die Komponente mit der Eigenschaft, deren Wert abgerufen werden soll.</param>
		/// <returns>
		/// Der Wert der beschriebenen Eigenschaft für die angegebene Komponente.
		/// </returns>
		public override object GetValue(object component)
		{
			if (component == null)
				throw new ArgumentNullException("component");
			return Accessor.Get(ParenDescriptor.GetValue(component));
		}

		/// <summary>
		/// Legt den Wert der beschriebenen Eigenschaft in der Komponente fest.
		/// </summary>
		/// <param name="component">Die Komponente mit dem Eigenschaftswert, der festgelegt werden soll.</param>
		/// <param name="value">Der neue Wert der Eigenschaft in der Komponente.</param>
		public override void SetValue(object component, object value)
		{
			if (component == null)
				throw new ArgumentNullException("component");
			Accessor.Set(ParenDescriptor.GetValue(component), value);
			base.OnValueChanged(component, new System.ComponentModel.PropertyChangedEventArgs(Name));
		}

		#endregion
	}
}